package algdat.dijkstra;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

/**
 * @author Mikko Puustinen (mikko.puustinen@gmail.com)
 * @version 0.1, 2007-dec-03
 */
public class Dijkstra {
    private int[] result;
    private int[][] weights;
    private boolean[] isVisited;
    private int startNode;
    private int endNode;
    private int nodes;
    private int paths;

    public Dijkstra() {
        result = new int[nodes];
        isVisited = new boolean[nodes];
        nodes = 0;
        paths = 0;
    }

    public void setUpPaths(String path) throws FileNotFoundException {
        Scanner scanner = new Scanner(new File(path));
        setNumberOfNodes(scanner.nextInt());
        setNumberOfPaths(scanner.nextInt());
        weights = new int[getNumberOfPaths()][3];
        result = new int[getNumberOfNodes()];
        isVisited = new boolean[getNumberOfNodes()];

        for (int i = 0; i < weights.length; i++) {
            weights[i][0] = scanner.nextInt() - 1;
            weights[i][1] = scanner.nextInt() - 1;
            weights[i][2] = scanner.nextInt();
        }

        /*for (int i = 0; i < weights.length; i++) {
            System.out.println(weights[i][0] + " " + weights[i][1] + " " + weights[i][2]);
        }*/
    }

    public void solve(int start, int end) {
        int currentNode = start;
        setStartNode(start);
        setEndNode(end);
        result[start] = 0;
        for (int i = 1; i < getNumberOfNodes(); i++) {
            result[i] = Integer.MAX_VALUE;
        }

        while (!isVisited[end]) {
            int min = Integer.MAX_VALUE;

            for (int i = 0; i < isVisited.length; i++) {
                if (!isVisited[i] && result[i] < min) {
                    min = result[i];
                    currentNode = i;
                }
            }

            isVisited[currentNode] = true;

            for (int i = 0; i < getNumberOfPaths(); i++) {
                int x = -1;

                if (weights[i][0] == currentNode) {
                    x = weights[i][1];
                }

                if (weights[i][1] == currentNode) {
                    x = weights[i][0];
                }

                if (x >= 0 && (result[x] > (result[currentNode] + weights[i][2]))) {
                    result[x] = (result[currentNode] + weights[i][2]);
                }
            }
        }

        //printResult();
    }

    public void printResult() {
        System.out.println("The shortest path to the nodes: ");

        for (int i = 0; i < result.length; i++) {
            System.out.println(i + 1 + " : " + result[i]);
        }
    }

    public void setStartNode(int startNode) {
        this.startNode = startNode;
    }

    public void setEndNode(int endNode) {
        if (endNode < 0 || endNode > getNumberOfNodes()) {
            throw new IllegalArgumentException("Error in specifying end node");
        }
        this.endNode = endNode;
    }

    private void setNumberOfNodes(int nodes) {
        this.nodes = nodes;
    }

    private void setNumberOfPaths(int paths) {
        this.paths = paths;
    }

    public int getStartNode() {
        return startNode;
    }

    public int getEndNode() {
        return endNode;
    }

    public int getNumberOfNodes() {
        return nodes;
    }

    public int getNumberOfPaths() {
        return paths;
    }
}
